package us.icitap.cm.ui.policecase;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import us.icitap.cm.CaseManagementUI;
import us.icitap.cm.business.entities.AppEntity;
import us.icitap.cm.business.entities.Case;
import us.icitap.cm.business.entities.EntityEntityAssociation;
import us.icitap.cm.business.entities.EntityTypeEnum;
import us.icitap.cm.business.entities.Report;
import us.icitap.cm.business.entities.ReportTypeEnum;
import us.icitap.cm.interfaces.ConfirmDialogAction;
import us.icitap.cm.listeners.AppEntityListener;
import us.icitap.cm.listeners.EntityEntityAssociationListener;
import us.icitap.cm.listeners.ReportListener;
import us.icitap.cm.listeners.ReturnObjectListener;
import us.icitap.cm.ui.custom.CustButton;
import us.icitap.cm.ui.custom.CustConfirmDialog;
import us.icitap.cm.ui.shared.AppEntityLayout;
import us.icitap.cm.ui.shared.GeneralVars;
import us.icitap.cm.ui.shared.LoadCaseWindow;
import us.icitap.cm.utils.HandleNotification;
import us.icitap.utils.Result;

import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.Action;
import com.vaadin.event.Action.Handler;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Tree;
import com.vaadin.ui.VerticalLayout;

public class SupplementReportLayout extends VerticalLayout implements AppEntityListener, EntityEntityAssociationListener, ReportListener{

	/**
	 * 
	 */
	private static final long serialVersionUID = -6889304428728479000L;

	
	Tree srTree = new Tree();
	Tree caseTree = new Tree();
	
	private final CustButton cb = new CustButton("Ruaj");
	
	final SupplementReportDataLayout srDataLayout = new SupplementReportDataLayout();
	final EventReportDataLayout erDataLayout = new EventReportDataLayout();
	final PersonDataLayout personDataLayout = new PersonDataLayout();
	final PlaceDataLayout placeDataLayout = new PlaceDataLayout();
	final VehicleDataLayout vehicleDataLayout = new VehicleDataLayout();
	final ItemDataLayout itemDataLayout = new ItemDataLayout();
	final WeaponDataLayout weaponDataLayout = new WeaponDataLayout();
	final DrugDataLayout drugDataLayout = new DrugDataLayout();
	final OrganizationDataLayout organizationDataLayout = new OrganizationDataLayout();
	final OfficerDataLayout officerDataLayout = new OfficerDataLayout();
	final EntityEntityAssocDataLayout assocDataLayout = new EntityEntityAssocDataLayout();
	final DocumentDataLayout docDataLayout = new DocumentDataLayout();
	final ControlDataLayout controlDataLayout = new ControlDataLayout();
	final ExperimentDataLayout experimentDataLayout = new ExperimentDataLayout();
	final ExpertiseDataLayout expertiseDataLayout = new ExpertiseDataLayout();
	
	
	final HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
	
	private Case pCase;


	Map<EntityTypeEnum , AppEntityLayout> map = new HashMap<EntityTypeEnum, AppEntityLayout>();
	
	
	public SupplementReportLayout() {
		final LoadCaseWindow loadCaseWindow = new LoadCaseWindow(false);
		loadCaseWindow.addListener(new ReturnObjectListener() {
			
			@Override
			public <T> void returnObject(T result) {
				if(result != null){
					loadUI();
					loadCase((Case) result);
					loadCaseWindow.close();
				}
			}
		});
		
		CaseManagementUI.getCurrent().addWindow(loadCaseWindow);
		
	}

	private void loadUI(){
		this.addComponent(splitPanel);
		
		VerticalLayout vl = new VerticalLayout();
		vl.addComponent(caseTree);
		vl.addComponent(srTree);
		
		
		cb.setSizeFull();
		vl.addComponent(cb);
		cb.addClickListener(new ClickListener() {
			
			@Override
			public void buttonClick(ClickEvent event) {
				CustConfirmDialog.show(getConfirmDialogAction(), getUI(), "Jeni i sigurte qe doni te ruani raportin e ngjarjes?");
				
			}
		});
		
		
		
		splitPanel.setFirstComponent(vl);
		
		splitPanel.setHeight("700px");
		splitPanel.setMinSplitPosition(200, Unit.PIXELS);
		splitPanel.setMaxSplitPosition(200, Unit.PIXELS);
		

		map.put(EntityTypeEnum.PLACE, this.placeDataLayout);
		map.put(EntityTypeEnum.PERSON, this.personDataLayout);
		map.put(EntityTypeEnum.VEHICLE, this.vehicleDataLayout);
		map.put(EntityTypeEnum.DRUG, this.drugDataLayout);
		map.put(EntityTypeEnum.WEAPON, this.weaponDataLayout);
		map.put(EntityTypeEnum.ITEM, this.itemDataLayout);
		map.put(EntityTypeEnum.ORGANIZATION, this.organizationDataLayout);
		map.put(EntityTypeEnum.OFFICER, this.officerDataLayout);
		map.put(EntityTypeEnum.DOCUMENT, this.docDataLayout);
		map.put(EntityTypeEnum.CONTROL, this.controlDataLayout);
		map.put(EntityTypeEnum.EXPERIMENT, this.experimentDataLayout);
		map.put(EntityTypeEnum.EXPERTISE, this.expertiseDataLayout);
		
		
		for (Iterator iterator = map.values().iterator(); iterator.hasNext();) {
			AppEntityLayout appEntityLayout = (AppEntityLayout) iterator.next();
			appEntityLayout.addAppEntityListener(this);
		}
		srDataLayout.addReportListener(this);
	
		
		srTree.addValueChangeListener(new ValueChangeListener() {
			
			@Override
			public void valueChange(ValueChangeEvent event) {
				if(event.getProperty() != null){
					if("ASSOCIATIONS".equals(event.getProperty().getValue())){
						if(pCase.getLastReport() == null){
							HandleNotification.showWarningOnScreen("Ne fillim duhet te ruani te dhenat kryesore e raportit suplementar");
							return;
						}
						SupplementReportLayout.this.splitPanel.setSecondComponent(assocDataLayout);
					}
					
					else if(ReportTypeEnum.SR.equals(event.getProperty().getValue())){
						SupplementReportLayout.this.splitPanel.setSecondComponent(srDataLayout);
					}
					else if (event.getProperty().getValue() instanceof AppEntity){
						AppEntity appEntity = (AppEntity) event.getProperty().getValue();
						loadAppEntity(appEntity);	
					}
					else if (event.getProperty().getValue() instanceof VerticalLayout){
							SupplementReportLayout.this.splitPanel.setSecondComponent((Component) event.getProperty().getValue());
						
						
					}
					
				}
				
			}
		});
		
		srTree.setImmediate(true);
		srTree.addActionHandler(new Handler() {
			
			@Override
			public void handleAction(Action action, Object sender, Object target) {

				if(action == GeneralVars.ADD){
					if(pCase.getLastReport() == null){
						HandleNotification.showWarningOnScreen("Ne fillim duhet te ruani te dhenat kryesore e raportit suplementar");
						return;
					}

					SupplementReportLayout.this.addAppEntity(EntityTypeEnum.valueOf(target.toString()));	
					srTree.select(target);
				}
				else if (action == GeneralVars.REMOVE){
					AppEntity appEntity = (AppEntity) target;
					
					CustConfirmDialog.show(
							SupplementReportLayout.this.getConfirmDialogActionRemoveAppEntity(appEntity), 
							CaseManagementUI.getCurrent(), "Jeni i sigurte qe doni te vazhdoni ta hiqni kete element? <br\\> Elementi nuk mund te rikthehet me por duhet te shtohet nga fillimi.");
				}
				
			}
			
			@Override
			public Action[] getActions(Object target, Object sender) {
				 if(target == null) return null;
				 if(target == EntityTypeEnum.PLACE
						 || target == EntityTypeEnum.PERSON
						 || target == EntityTypeEnum.VEHICLE
						 || target == EntityTypeEnum.WEAPON
						 || target == EntityTypeEnum.DRUG
						 || target == EntityTypeEnum.ORGANIZATION
						 || target == EntityTypeEnum.ITEM
						 || target == EntityTypeEnum.OFFICER
						 || target == EntityTypeEnum.DOCUMENT
						 || target == EntityTypeEnum.CONTROL
						 || target == EntityTypeEnum.EXPERIMENT
						 || target == EntityTypeEnum.EXPERTISE)
	               return new Action[]{GeneralVars.ADD};
				 if(target instanceof AppEntity){
					 return new Action[]{GeneralVars.REMOVE};
				 }
				 return null;
			}
		});
		
		caseTree.setImmediate(true);
		
		caseTree.addValueChangeListener(new ValueChangeListener() {
			
			@Override
			public void valueChange(ValueChangeEvent event) {
				if(event.getProperty() != null){
					
					if (event.getProperty().getValue() instanceof VerticalLayout){
							SupplementReportLayout.this.splitPanel.setSecondComponent((Component) event.getProperty().getValue());
							System.out.println(CaseManagementUI.getCurrent().getPage().getBrowserWindowHeight());
					}
				}	
			}
		});
		
	}
	
	private void loadCase(Case _case){
		this.pCase = _case;
		Report lastReport = pCase.getLastReport();

		Report report = new Report(CaseManagementUI.getUser().getUsername());
		report.setReportOfficer(CaseManagementUI.getUser().getOfficer());
		report.setOrgStructure(CaseManagementUI.getUser().getOrgStructure());
		report.setRecordUser(CaseManagementUI.getUser().getUsername());
		report.setReportType(ReportTypeEnum.SR);

		int nr = pCase.getSupplementReportNumber();
		report.setTempUniqueNumber(pCase.getCaseId() + "/" + (nr+1));
		
		

		report.addReportAppEntityList(lastReport.getEntityList());
		

		if(lastReport.getEntityEntityAssocList() != null){
			List<EntityEntityAssociation> list = new ArrayList<EntityEntityAssociation>();
			for (EntityEntityAssociation eea : lastReport.getEntityEntityAssocList()) {
				EntityEntityAssociation newEea = new EntityEntityAssociation();
				newEea.setReport(report);
				newEea.setEntityOne(eea.getEntityOne());
				newEea.setEntityTwo(eea.getEntityTwo());
				newEea.setAssociationType(eea.getAssociationType());
				newEea.setNotes(eea.getNotes());
				newEea.setRecordDate(new Date());
				list.add(newEea);
			}
			report.addEntityEntityAssociationList(list);
		}
			
		report.setPrimaryPoliceCode(lastReport.getPrimaryPoliceCode());
		report.setPoliceCodeList(lastReport.getPoliceCodeList());
		
		
		this.pCase.setLastReport(null);
		this.populateTree(report);
		srDataLayout.addReport(report);
		controlDataLayout.setReport(report);
		assocDataLayout.setReport(report);
		assocDataLayout.addEntityEntityAssociationListener(this);
		
		
		
		SupplementReportLayout.this.splitPanel.setSecondComponent(srDataLayout);
		
		cb.setEnabled(false);
		
	}
	
	private void populateTree(Report newReport){
		
		
//		Report lastReport = pCase.getLastReport();
		
		srTree.addItem(ReportTypeEnum.SR);
		srTree.setItemCaption(ReportTypeEnum.SR, newReport.getTempUniqueNumber() + ", " + newReport.getPrimaryPoliceCode().toString());
		
		
		srTree.addItem(EntityTypeEnum.PLACE);
		srTree.setItemCaption(EntityTypeEnum.PLACE, EntityTypeEnum.PLACE.getCaption());
		srTree.setParent(EntityTypeEnum.PLACE, ReportTypeEnum.SR);
		
		srTree.addItem(EntityTypeEnum.PERSON);
		srTree.setItemCaption(EntityTypeEnum.PERSON, EntityTypeEnum.PERSON.getCaption());
		srTree.setParent(EntityTypeEnum.PERSON, ReportTypeEnum.SR);
		
		srTree.addItem(EntityTypeEnum.DOCUMENT);
		srTree.setItemCaption(EntityTypeEnum.DOCUMENT, EntityTypeEnum.DOCUMENT.getCaption());
		srTree.setParent(EntityTypeEnum.DOCUMENT, ReportTypeEnum.SR);
		
		srTree.addItem(EntityTypeEnum.VEHICLE);
		srTree.setItemCaption(EntityTypeEnum.VEHICLE, EntityTypeEnum.VEHICLE.getCaption());
		srTree.setParent(EntityTypeEnum.VEHICLE, ReportTypeEnum.SR);
		
		srTree.addItem(EntityTypeEnum.ITEM);
		srTree.setItemCaption(EntityTypeEnum.ITEM, EntityTypeEnum.ITEM.getCaption());
		srTree.setParent(EntityTypeEnum.ITEM, ReportTypeEnum.SR);
		
		srTree.addItem(EntityTypeEnum.DRUG);
		srTree.setItemCaption(EntityTypeEnum.DRUG, EntityTypeEnum.DRUG.getCaption());
		srTree.setParent(EntityTypeEnum.DRUG, ReportTypeEnum.SR);
		
		srTree.addItem(EntityTypeEnum.WEAPON);
		srTree.setItemCaption(EntityTypeEnum.WEAPON, EntityTypeEnum.WEAPON.getCaption());
		srTree.setParent(EntityTypeEnum.WEAPON, ReportTypeEnum.SR);
		
		srTree.addItem(EntityTypeEnum.ORGANIZATION);
		srTree.setItemCaption(EntityTypeEnum.ORGANIZATION, EntityTypeEnum.ORGANIZATION.getCaption());
		srTree.setParent(EntityTypeEnum.ORGANIZATION, ReportTypeEnum.SR);
		
		srTree.addItem(EntityTypeEnum.OFFICER);
		srTree.setItemCaption(EntityTypeEnum.OFFICER, EntityTypeEnum.OFFICER.getCaption());
		srTree.setParent(EntityTypeEnum.OFFICER, ReportTypeEnum.SR);
		
		srTree.addItem(EntityTypeEnum.CONTROL);
		srTree.setItemCaption(EntityTypeEnum.CONTROL, EntityTypeEnum.CONTROL.getCaption());
		srTree.setParent(EntityTypeEnum.CONTROL, ReportTypeEnum.SR);
		
		srTree.addItem(EntityTypeEnum.EXPERIMENT);
		srTree.setItemCaption(EntityTypeEnum.EXPERIMENT, EntityTypeEnum.EXPERIMENT.getCaption());
		srTree.setParent(EntityTypeEnum.EXPERIMENT, ReportTypeEnum.SR);
		
		srTree.addItem(EntityTypeEnum.EXPERTISE);
		srTree.setItemCaption(EntityTypeEnum.EXPERTISE, EntityTypeEnum.EXPERTISE.getCaption());
		srTree.setParent(EntityTypeEnum.EXPERTISE, ReportTypeEnum.SR);
		
		srTree.addItem("ASSOCIATIONS");
		srTree.setItemCaption("ASSOCIATIONS", "Lidhjet");
		srTree.setParent("ASSOCIATIONS", ReportTypeEnum.SR);
		
		srTree.expandItemsRecursively(ReportTypeEnum.SR);
		
		if(newReport.getEntityList() != null && !newReport.getEntityList().isEmpty()){
			for (AppEntity appEntity : newReport.getEntityList()) {
				this.addAppEntityToTree(appEntity);
			}
		}
		
		caseTree.addItem("CASE");
		
		for (Report r : pCase.getReportList()) {
			VerticalLayout vl;
			if(r.getReportType().equals(ReportTypeEnum.ER)){
				vl = ViewCaseLayout.showEventReport(r); 
				caseTree.addItem(vl);
				caseTree.setItemCaption(vl, r.toString());
				caseTree.setParent(vl, "CASE");
			}
			else if(r.getReportType().equals(ReportTypeEnum.SR)){
				vl = ViewCaseLayout.showSupplementReport(r);
				caseTree.addItem(vl);
				caseTree.setItemCaption(vl, r.toString());
				caseTree.setParent(vl, "CASE");
			}
			
		}
		caseTree.expandItemsRecursively("CASE");
		
		
	}
	

	private void loadAppEntity(AppEntity appEntity){
		if(pCase.getLastReport() == null){
			HandleNotification.showWarningOnScreen("Ne fillim duhet te ruani te dhenat kryesore e raportit suplementar");
			return;
		}
		
		AppEntityLayout appEntityLayout = map.get(appEntity.getEntityType());
		
		appEntityLayout.loadAppEntity(appEntity, true);
		
		SupplementReportLayout.this.splitPanel.setSecondComponent(appEntityLayout);
	}
	
	private void addAppEntity(EntityTypeEnum entityTypeEnum){
		AppEntityLayout appEntityLayout = map.get(entityTypeEnum);
		appEntityLayout.addAppEntity();
		
		SupplementReportLayout.this.splitPanel.setSecondComponent(appEntityLayout);
	}
	
	private void addAppEntityToTree(AppEntity appEntity){
		this.srTree.addItem(appEntity);
		this.srTree.setParent(appEntity,appEntity.getEntityType());

		this.srTree.setItemCaption(appEntity.getEntityType(), appEntity.getEntityType().getCaption() + "(" + srTree.getChildren(appEntity.getEntityType()).size() + ")");

	}
	


	
	private ConfirmDialogAction getConfirmDialogAction(){
		ConfirmDialogAction confirm = new ConfirmDialogAction(){

			@Override
			public void actYes() {
	
				
				Result<Case> result =CaseManagementUI.appStatelessBean.getPersistenceBean().saveReport(pCase);
				if(result.isSucceeded()){
					HandleNotification.showInfoOnTray("Ceshtja u ruajt me sukses");
//					loadCase(result.getObject());
					
				}
					
					
				else
					HandleNotification.showErrorOnScreen(result.getMessage());
				
			}

			@Override
			public void actNO() {
				// TODO Auto-generated method stub
				
			}
			
		};
		return confirm;
	}

	@Override
	public void storeInMemory(Report report) {
		
		pCase.addReport(report);
		report.setPoliceCase(pCase);
		pCase.setLastReport(report);
		
		cb.setEnabled(true);
	}
	
	private ConfirmDialogAction getConfirmDialogActionRemoveAppEntity(final AppEntity appEntity){
		ConfirmDialogAction confirm = new ConfirmDialogAction(){

			@Override
			public void actYes() {
				removeAppEntityFromReport(appEntity);
				HandleNotification.showInfoOnTray("Elementi :" + appEntity.getEntityType().getCaption() + " : " + appEntity.toString() + " u hoq me sukses."  );
			}

			@Override
			public void actNO() {
				
				
			}
			
		};
		
		return confirm;
	}

	@Override
	public void addAppEntityToReport(AppEntity appEntity) {
		if(appEntity != null){
			if(appEntity.getEntityType().equals(EntityTypeEnum.CONTROL)){
				appEntity.getControl().setReport(pCase.getLastReport());
				pCase.getLastReport().addControl(appEntity.getControl());
			}
			else{
				pCase.getLastReport().addAppEntity(appEntity);
//				pCase.getLastReport().addEntityReportAssociationList(appEntity.getReportAssociationList());
			}
			
			this.addAppEntityToTree(appEntity);
	
		}
		
	}


	@Override
	public void removeAppEntityFromReport(AppEntity appEntity) {
		
		if(pCase.getLastReport().getEntityEntityAssocList() != null){
			for (Iterator<EntityEntityAssociation> iterator = pCase.getLastReport().getEntityEntityAssocList().iterator(); iterator.hasNext();) {
				EntityEntityAssociation eea = iterator.next();
				if(eea.getEntityOne().equals(appEntity)) iterator.remove();
				else if(eea.getEntityTwo().equals(appEntity)) iterator.remove();
			}
		}
		
		pCase.getLastReport().removeAppEntity(appEntity);
		
		srTree.removeItem(appEntity);
		if(srTree.getChildren(appEntity.getEntityType()) == null)
			srTree.setItemCaption(appEntity.getEntityType(), appEntity.getEntityType().getCaption());
		else
			srTree.setItemCaption(appEntity.getEntityType(), appEntity.getEntityType().getCaption() + "(" + srTree.getChildren(appEntity.getEntityType()).size() + ")");
		
		
	}

	@Override
	public void refresh(AppEntity appEntity) {
		srTree.markAsDirty();
		
	}

	@Override
	public void updateAppEntityIntoReport(AppEntity oldValue, AppEntity newValue) {
		
		pCase.getLastReport().removeAppEntity(oldValue);
		
		if(pCase.getLastReport().getEntityEntityAssocList() != null){
			for (EntityEntityAssociation eea : pCase.getLastReport().getEntityEntityAssocList()) {
				if(eea.getEntityOne().equals(oldValue)) eea.setEntityOne(newValue);
				if(eea.getEntityTwo().equals(oldValue)) eea.setEntityTwo(newValue);
			}
		}

		srTree.removeItem(oldValue);

		pCase.getLastReport().addAppEntity(newValue);
		
		

		
		
		this.addAppEntityToTree(newValue);
		srTree.markAsDirty();
	}

	@Override
	public void addEntityEntityAssociation(EntityEntityAssociation eea) {
		if (pCase.getLastReport().getEntityEntityAssocList() != null && !pCase.getLastReport().getEntityEntityAssocList().isEmpty()){
			for (EntityEntityAssociation e : pCase.getLastReport().getEntityEntityAssocList()) {
				if(e.myEquals(eea)) return;
			}
			eea.getEntityOne().addEntityAssocAsOne(eea);
			eea.getEntityTwo().addEntityAssocAsTwo(eea);
			eea.setReport(pCase.getLastReport());
			pCase.getLastReport().addEntityEntityAssociation(eea);
		}
		
	}

	@Override
	public void removeEntityEntityAssociation(EntityEntityAssociation eea) {
		if (pCase.getLastReport().getEntityEntityAssocList() != null && !pCase.getLastReport().getEntityEntityAssocList().isEmpty()){
			for (EntityEntityAssociation e : pCase.getLastReport().getEntityEntityAssocList()) {
				if(e.myEquals(eea)) {
					pCase.getLastReport().getEntityEntityAssocList().remove(e);
					return;
				}
			}
		}
		
	}
}
